import ij.IJ;
import ij.ImagePlus;
import ij.gui.NewImage;
import ij.io.FileSaver;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.awt.Polygon;
import java.io.PrintStream;

import java.util.Iterator;
import java.util.Locale;
import java.util.Random; 



import pluginUtils.Circle;
import pluginUtils.CircleArrangement;
import pluginUtils.Complexe; 
import pluginUtils.DoyleCircle;
import pluginUtils.MobiusTransform;
import pluginUtils.CircleInversion;
import pluginUtils.PackCircle;
import pluginUtils.Plane;
import pluginUtils.Pos3D;
import pluginUtils.Sphere;
import pluginUtils.SphereInversion;
import sliceformUtils.CoupleDAngles;
import sliceformUtils.Ligne;
import sliceformUtils.Mesh;
import sliceformUtils.STLReader;
import sliceformUtils.Saucisson;
import sliceformUtils.Segment;
import sliceformUtils.Triangle;


public class Sliceform extends ImagePlus implements PlugIn{
	{Locale.setDefault(Locale.US); }
	
	private ImageProcessor primeIP; 
	private int X=2000,Y=2000; // image size
	
	private PrintStream output;
	private double xShift=0; 
	private double zShift=0; 
	
	

	private Random generator=new Random(); // One always needs some randomness
	
	// For the scaling of the image
	private double x0=0,x1=1,y0=0,y1=1;
	private double acoef,ccoef,vcoef,wcoef; 
	
	public void setCoefs(){
		acoef=X/(x1-x0); 
		vcoef=Y/(y1-y0); 
		ccoef=-acoef*x0; 
		wcoef=-vcoef*y0; 
	}
	 
	
	
	public void setBounds(double xl,double xu,double yl,double yu){
		x0=xl; 
		x1=xu;
		y0=yl;
		y1=yu; 
	}
	
	
	
	private void drawLine(double xd,double yd,double xf,double yf){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		primeIP.drawLine(XD,YD,XF,YF); 
	}
	
	private void drawLine(double xd,double yd,double xf,double yf,ImageProcessor ip){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		ip.drawLine(XD,YD,XF,YF); 
	}
	
	/*
	public Saucisson tranches(Mesh leMesh,Plane lePlan,int n){
		
	}
		
	*/
	
	/** Calcule les angles de rotation amenant un plan parallele a un plan perpendiculaire a ox **/
	/*
	public CoupleDAngles rotations(Plane p){
		CoupleDAngles resu=new CoupleDAngles(); 
		if(p.getA()==0){
			if(p.getB()==0){
				resu.setAlpha(0); 
				if(p.getC()<0) resu.setBeta(Math.PI/2); else resu.setBeta(Math.PI/2); 
				return resu;
			}
			else // A=0 et B!=0
				resu
		}
		
	}
	*/
	
	
	public void run(String arg) {
		primeIP = new ColorProcessor(X,Y);
		double r2=Math.sqrt(2);
		
		double limit=1; 
		double lmoins=-1;
	
		setBounds(lmoins,limit,lmoins,limit); 
		setCoefs(); 
		
	
		
		Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
		primeIP.setColor(Color.WHITE);
		
		primeIP.fillPolygon(background);
		
		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.BLACK);
		primeIP.setLineWidth(2); 
		

		setProcessor("Verifying", primeIP);
		
		
		primeIP.setColor(Color.BLACK);
		primeIP.setLineWidth(5);
		Mesh leMesh=null; 
		try{
		leMesh=STLReader.readMesh("/tmp/bunny2.stl");
		}
		catch(Exception e){System.out.println(e); System.exit(0); }
		
		
		/* determiner la taille de l'image : a completer
		 * si on coupe aussi dans une autre direction
		 */
		System.out.println(leMesh.info()); 
		double bmin=leMesh.getMinY(),bmax,cmin=leMesh.getMinZ(),cmax; 
		if(leMesh.getYwide()>leMesh.getZwide())
			{bmax=leMesh.getYwide(); cmax=leMesh.getYwide();}
		else
		    {bmax=leMesh.getZwide(); cmax=leMesh.getZwide();}
		
		// decoupage par des plan perpendiculaires a l'axe Ox
		double xMin=leMesh.getMinX(); 
		double xMax=leMesh.getMaxX(); 
		int n=5; 
		double pos=xMin+leMesh.getXwide()/(2.0*n); 
		
		for(int i=0;i<n;i++){
		ImagePlus gamma=NewImage.createRGBImage ("Image"+i,X,Y, 1, NewImage.FILL_WHITE);	
		ImageProcessor i1=gamma.getProcessor();
		FileSaver fs=new FileSaver(gamma); 
		i1.setColor(Color.BLACK);
		i1.setLineWidth(5);
		Plane lePlan=new Plane(1,0,0,-pos);
		System.out.println("-->"+pos);
		pos=pos+leMesh.getXwide()/n;
		Ligne contour=new Ligne(lePlan);
		Iterator<Triangle> it=leMesh.iterator(); 
		while(it.hasNext()){
			Triangle tr=it.next(); 
			//System.out.println(tr);
			if (tr.isCut(lePlan)) { contour.add(tr.coupePar(lePlan));}		
		}
		System.out.println(i+"\n"+contour.info()+"\n"); 
		
		double marge=1; 
		setBounds(bmin-marge,bmax+marge,cmin-marge,cmax+marge); 
		setCoefs(); 
		Iterator<Segment> itS=contour.iterator(); 
		while(itS.hasNext()){
			Segment seg=itS.next(); 
			Pos3D s1=seg.getOne(); 
			Pos3D s2=seg.getTwo(); 
			//System.out.println(seg); 
			drawLine(s1.getY(),bmax+marge-s1.getZ(),s2.getY(),bmax+marge-s2.getZ(),i1); 
		}
		gamma.show(); 
		fs.saveAsPng("/tmp/bunnyX"+i+".png"); 
		} // tranches
		
		// TODO : decoupages par des plans perpendiculaires a Oy
		
		/*
		double yMin=leMesh.getMinY(); 
		double yMax=leMesh.getMaxY(); 
		 
		pos=yMin+leMesh.getYwide()/(2.0*n); 
		
		for(int i=0;i<n;i++){
		ImagePlus gamma=NewImage.createRGBImage ("ImageY"+i,X,Y, 1, NewImage.FILL_WHITE);	
		ImageProcessor i1=gamma.getProcessor();
		FileSaver fs=new FileSaver(gamma); 
		i1.setColor(Color.BLACK);
		i1.setLineWidth(5);
		Plane lePlan=new Plane(0,1,0,-pos);
		System.out.println("-->"+pos);
		pos=pos+leMesh.getYwide()/n;
		Ligne contour=new Ligne();
		Iterator<Triangle> it=leMesh.iterator(); 
		while(it.hasNext()){
			Triangle tr=it.next(); 
			//System.out.println(tr);
			if (tr.isCut(lePlan)) { contour.add(tr.coupePar(lePlan));}		
		}
		System.out.println(i+"\n"+contour.info()+"\n"); 
		
		double marge=1; 
		setBounds(bmin-marge,bmax+marge,cmin-marge,cmax+marge); 
		setCoefs(); 
		Iterator<Segment> itS=contour.iterator(); 
		while(itS.hasNext()){
			Segment seg=itS.next(); 
			Sommet s1=seg.getOne(); 
			Sommet s2=seg.getTwo(); 
			//System.out.println(seg); 
			drawLine(s1.getX(),bmax+marge-s1.getZ(),s2.getX(),bmax+marge-s2.getZ(),i1); 
		}
		gamma.show(); 
		fs.saveAsPng("/tmp/bunnyY"+i+".png"); 
		} // tranches
		 */
		
	}	
}
	